import random
from django import forms
from web import models

from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from trance import local_settings
from utils.tencent.sms import send_sms_single 
from django_redis import get_redis_connection
from utils import encrypt
from web.forms.bootstrap import BootStrapForm

class RegisterModelForm(BootStrapForm,forms.ModelForm):
    
    # password = forms.CharField(label='密码',
    # widget=forms.PasswordInput(attrs={'class':"form-control",'placeholder':"请输入密码"}))
    password = forms.CharField(label='密码',
    min_length=8,
    max_length=64,
    error_messages = {
        'min_length':"密码长度不能小于8个字符",
        "max_length":"密码长度不能大于64个字符"
    },
    widget=forms.PasswordInput())

    confirm_password = forms.CharField(label='确认密码',
    min_length=8,
    max_length=64,
    error_messages= {
        'min_length':"重复密码长度不能小于8个字符",
        "max_length":"重复密码长度不能大于64个字符"
    },
    widget=forms.PasswordInput())

    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    code = forms.CharField(label='验证码')
    class Meta:
        model = models.UserInfo
        #fields = "__all__"
        fields = ['username','password','confirm_password','email','mobile_phone','code']

   
    
    def clean_username(self):
        username = self.cleaned_data['username']

        exists = models.UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户名已存在')

        return username

    def clean_password(self):
        pwd = self.cleaned_data['password']
        print("===============================")
        print(pwd)

        # 密码加密&返回
        pwd = encrypt.md5(pwd)
        print(pwd)
        return pwd

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data['confirm_password']
        confirm_password = encrypt.md5(confirm_password)
        print(confirm_password)

        if pwd != confirm_password:
            raise ValidationError('两次密码不一致')
        return confirm_password

    def clean_email(self):
        email = self.cleaned_data["email"]
        exists = models.UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('邮箱已存在')
        
        return email

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']

        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exists:
            return ValidationError('手机号已注册')

        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data['code']
        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not mobile_phone:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError("验证码失效或未发送，请重新获取验证码")

        redis_str_code = redis_code.decode('utf8')
        if code.strip() != redis_str_code:
            raise ValidationError("验证码错误,请重新输入")

        return code
        

class SendSmsForm(forms.Form):
    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])

    def __init__(self,request,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.request = request

    def clean_mobile_phone(self):
        """手机号校验的钩子"""
        mobile_phone = self.cleaned_data['mobile_phone']

        # 判断短信模板是否有问题
        tpl = self.request.GET.get('tpl')
        template_id = local_settings.TENCENT_SMS_TEMPLATE.get(tpl)
        if not template_id:
            raise ValidationError("短信模板错误")
        
        exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if tpl == 'login':
            if not exists:
                raise ValidationError('手机号不存在')
        else:
            # 校验数据库中是否已经存在手机号
            
            if exists:
                raise ValidationError("手机号已存在")
       
        # 发送短信
        code = random.randrange(1000,9999)
        sms = send_sms_single(mobile_phone, template_id, [code,])
        if sms['result'] != 0:
            raise ValidationError("短信发送失败{}".format(sms['errmsg']))

        # 短信验证码写入redis(django-redis)
        conn = get_redis_connection()
        conn.set(mobile_phone,code,ex=60)   
        
        return mobile_phone

class LoginSmsForm(BootStrapForm,forms.Form):
    mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])
    code = forms.CharField(label='验证码')

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']

        #exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        usr_obj = models.UserInfo.objects.filter(mobile_phone=mobile_phone).first()
        if not usr_obj:
            return ValidationError('手机号不存在')

        return usr_obj

    def clean_code(self):
        code = self.cleaned_data['code']
        usr_obj = self.cleaned_data.get('mobile_phone')
        
        # 手机号不存在验证码无需再验证
        if not usr_obj:
            return code

        conn = get_redis_connection()
        redis_code = conn.get(usr_obj.mobile_phone)
        if not redis_code:
            raise ValidationError("验证码失效或未发送，请重新获取验证码")

        redis_str_code = redis_code.decode('utf8')
        if code.strip() != redis_str_code:
            raise ValidationError("验证码错误,请重新输入")

        return code

class LoginForm(BootStrapForm,forms.Form):
    username = forms.CharField(label='邮箱或手机号')
    password = forms.CharField(label='密码',widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label='图片验证码')

    # 利用类的__init__魔术方法将views视图中的request参数传递到本类中
    def __init__(self,request,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.request = request

    def clean_password(self):
        pwd = self.cleaned_data['password']
        # 密码加密&返回
        pwd = encrypt.md5(pwd)
        return pwd

    def clean_code(self):
        """验证码校验的钩子"""

        # 读取用户输入的验证码
        code = self.cleaned_data['code']

        # 获取session中存储的验证码
        session_code = self.request.session.get('code')
        if not session_code:
            raise ValidationError('验证码失效,请重新获取！')

        # 比较两次输入验证码是否一致
        if code.strip().upper() != session_code.strip().upper():
            raise ValidationError('验证码错误！')